<template>
  <div class="x-data-table">
    <div v-if="toolbar || title" class="toolbar flex">
      <div class="toolbar-left flex-item">
        <div class="toolbar-title">
          <template v-if="title">
            {{ title }}
          </template>
          <slot name="tableTitle" />
        </div>
      </div>
      <div v-if="toolbar" class="toolbar-right">
        <slot name="toolbar" />
        <!--导出下载-->
        <n-tooltip v-if="exportAction" trigger="hover">
          <template #trigger>
            <n-button class="mr-10" type="primary" text :size="buttonSize" @click="handleDownload">
              {{ exportLoading ? '导出中...' : exportText }}
            </n-button>
          </template>
          <span>{{ exportLoading ? '导出中...' : exportText }}</span>
        </n-tooltip>
        <!--刷新-->
        <n-tooltip v-if="isReload" trigger="hover">
          <template #trigger>
            <div class="table-toolbar-right-icon" @click="reload">
              <n-icon size="18">
                <ReloadOutlined />
              </n-icon>
            </div>
          </template>
          <span>刷新</span>
        </n-tooltip>
      </div>
    </div>

    <div v-if="$slots.notice" class="notice">
      <slot name="notice" />
    </div>

    <div class="table-list">
      <n-data-table
        ref="tableElRef"
        v-bind="props"
        :loading="pagination.loading"
        :data="tableData"
        :size="tableSize"
        :render-cell="renderCell"
        :columns="myColumns"
        :max-height="myMaxHeight"
      >
        <template #empty>
          <slot v-if="$slots.empty" name="empty" />
          <div v-else class="empty">
            <img :src="IconEmpty" class="empty__icon" alt="暂无数据" />
            <n-text depth="3">暂无数据</n-text>
          </div>
        </template>
      </n-data-table>
      <div v-if="$slots.summary" class="summary">
        <slot name="summary" />
      </div>
    </div>
    <div class="pagination">
      <x-pagination
        ref="paginationElRef"
        v-bind="pagination"
        v-model:immediate="pagination.immediate"
        v-model:loading="pagination.loading"
        :show-quick-jumper="showQuickJumper"
        :params="params"
        @change="setTableData"
      />
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, reactive, toRefs, watch, ref, nextTick, h, computed } from 'vue'
  import { NDataTable, NTooltip, NButton, NIcon, NText } from 'naive-ui'
  import { ReloadOutlined } from '@vicons/antd'
  import { XPagination } from '../x-pagination'
  import { getObjectValue } from '@/utils'
  import IconEmpty from '@/assets/images/empty.png'
  import { isPC } from '@/utils/is'
  import { useExport } from '@/hooks'

  export default defineComponent({
    name: 'XDataTable',
    components: {
      NDataTable,
      NTooltip,
      NIcon,
      ReloadOutlined,
      NButton,
      NText,
      XPagination
    },
    props: {
      ...NDataTable.props,
      title: {
        type: String,
        default: ''
      },
      params: {
        type: Object,
        default: () => ({})
      },
      immediate: {
        type: Boolean,
        default: false
      },
      // 是否显示工具栏
      toolbar: {
        type: Boolean,
        default: true
      },
      page: {
        type: Number,
        default: 1
      },
      size: {
        type: Number,
        default: 20
      },
      // 数据节点
      dataField: {
        type: String,
        default: 'data'
      },
      exportText: {
        type: String,
        default: '导出'
      },
      // 导出的store.dispatch.action
      exportAction: {
        type: String,
        default: ''
      },
      // 导出文件名前缀
      exportNamePrefix: {
        type: String,
        default: ''
      },
      // 导出文件的类型
      exportType: {
        type: String,
        default: '.xls'
      },
      pageSizes: {
        type: Array,
        default: () => [10, 20, 30, 50, 100]
      },
      maxHeight: {
        type: [Number, String],
        default: () => 'calc(100vh - 300px)'
      },
      showQuickJumper: {
        type: Boolean,
        default: true
      },
      isReload: {
        type: Boolean,
        default: true
      },
      buttonSize: {
        type: String,
        default: 'medium'
      }
    },
    emits: ['change', 'update:immediate'],
    setup($props, { emit: $emit }) {
      const paginationElRef: any = ref(null)
      const { exportSheets } = useExport()
      const $state = reactive({
        ...toRefs($props),
        myColumns: computed(() => {
          const columns = $props.columns
          if (!isPC()) {
            columns.forEach((item) => {
              item.fixed = false
            })
          }
          return columns
        }),
        myMaxHeight: computed(() => {
          if (isPC()) {
            return $props.maxHeight
          } else {
            return 'auto'
          }
        }),
        props: toRefs($props),
        exportLoading: false,
        pagination: {
          loading: false,
          immediate: $props.immediate,
          page: $props.page,
          size: $props.size,
          pageSizes: $props.pageSizes
        },
        tableData: [],
        tableSize: 'small',
        buttonSize: $props.buttonSize,
        renderCell: (value: string | number) => {
          if (!value && value !== 0) {
            return h(NText, { depth: 3 }, { default: () => '-' })
          }
          return value
        }
      })

      // watch
      watch(
        () => $props.immediate,
        (value) => {
          if (value) {
            $state.tableData = []
            $state.pagination.page = 1
            $state.pagination.immediate = value
          }
        }
      )

      watch(
        () => $state.pagination.immediate,
        (value) => {
          if (!value) {
            $emit('update:immediate', false)
          }
        }
      )

      // 处理获取的数据
      const setTableData = (res: any, pagination: { page: number; pageSize: number }) => {
        $emit('update:immediate', false)
        $emit('change', res, pagination)
        $state.pagination = {
          ...$state.pagination,
          ...pagination
        }
        // 根据dataField获取接口返回数据对应字段，默认res.data
        const list = getObjectValue(res, $props.dataField)
        $state.tableData = list || []
      }

      // 刷新数据
      const reload = () => {
        if (paginationElRef.value) {
          paginationElRef.value.getData()
        }
      }

      // 强制重新请求
      const reset = () => {
        if (paginationElRef.value) {
          $emit('update:immediate', false)
          $state.pagination.page = $props.page
          $state.pagination.size = $props.size
          nextTick(() => {
            paginationElRef.value.getData()
          })
        }
      }

      // 导出下载
      const handleDownload = () => {
        if ($state.exportLoading) return false
        $state.exportLoading = true
        exportSheets(
          $props.exportAction,
          {
            ...$props.params.data,
            pageNum: $state.pagination.page,
            pageSize: $state.pagination.size
          },
          $props.exportNamePrefix
        )
          .then(() => {
            $state.exportLoading = false
          })
          .catch(() => {
            $state.exportLoading = false
          })
      }

      return {
        ...toRefs($state),
        paginationElRef,
        reset,
        reload,
        setTableData,
        handleDownload,
        IconEmpty
      }
    }
  })
</script>

<style lang="scss">
  .x-data-table {
    .table-list {
      tr.is-active td {
        background-color: #ebf5ef;
      }
    }
  }
</style>

<style lang="scss" scoped>
  .x-data-table {
    .toolbar {
      position: relative;
      padding-bottom: 12px;
      .toolbar-right {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        margin-left: 10px;
      }
      .table-toolbar-right-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        margin: 0 8px;
        cursor: pointer;
      }
    }
    .pagination {
      padding-top: 12px;
      display: flex;
      justify-content: flex-end;
    }

    .notice {
      padding-bottom: 12px;
    }

    .empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      &__icon {
        width: 60px;
        margin-bottom: 10px;
      }
    }
    .summary {
      margin-top: 10px;
    }
  }
</style>
